
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <daha.h>
#include <pm.h>
#include <mm.h>
#include <sched.h>

#define DAHA_DEMO

const char *state_names[] = {"NEW","READY","WAITING","RUNNING","TERMND"};
const char *page_state_names[] = {"FREE", "ALLOC", "FAULTED", "INMEM",
																											 "SAWPPNG", "SWAPPED"};

void print_sched_state(){
	struct fs_sched_state *state = get_sched_state();
	printf("Scheduler state:\n");
	printf("  Total shareable = %d\n",state->total_cycles);
	printf("  Current cycle   = %d\n",state->current_cycle);
	printf("  # active groups = %d\n",state->n_active_groups);
	printf("  Group slice     = %d\n",state->slice_group);
}

void print_process_list_header(int separator){
	printf("PID\tGR\tState\tProc\tQNTM\tLEFT\tSOFAR\t#PGS\tCMD\n");
	if(separator)
		printf("==================================="
																	"==================================\n");
}


struct process** get_all_processes(int* size)
{
  int n_procs = new_queue.n_elements + ready_queue.n_elements 
							+ waiting_queue.n_elements + terminated_queue.n_elements 
							+ NUM_PROC;
	struct process **list;
	struct process *p;
	int i = 0,j;
	
//	printf("n_procs=%d\n",n_procs);
	list = (struct process**)malloc(n_procs * sizeof(struct process*));
//	printf("list allocated\n");
		
	p = new_queue.head;
	while(p != NULL){
		list[i++] = p;
		p = p->next_p;
	}
	
	p = ready_queue.head;
	while(p != NULL){
		list[i++] = p;
		p = p->next_p;
	}
	
	p = waiting_queue.head;
	while(p != NULL){
		list[i++] = p;	
		p = p->next_p;
	}
	
	p = terminated_queue.head;
	while(p != NULL){
		list[i++] = p;
		p = p->next_p;
	}
	
	for(j=0; j < NUM_PROC; j++){
		p = running_list[j];
		if(p != NULL) list[i++] = p;
	}
	
	*size = i;
	
	return list;
}

//this simply prints data about a process to the console
void print_process(struct process* p)
{
	int q,left;
	if(p->pid == 0){
		printf("0\t0\tKERN\t-\t-\t-\t-\t%d\t%s\n", p->pt.size, p->cmd);							
	} else if(p->state == P_RUNNING || p->state == P_READY){
		calculate_quantum_and_cycles_left(p,&q,&left);
		printf("%d\t%d\t%s\t%d\t%d\t%d\t%d\t%d\t%s\n", p->pid,p->sched.group_no,
														state_names[p->state], p->processor_number,
														q,p->state == P_RUNNING ? left : -1,
														p->stats.time_run, p->pt.size, p->cmd);
	} else {
		printf("%d\t%d\t%s\t%d\t-\t-\t%d\t%d\t%s\n", p->pid,p->sched.group_no,
														state_names[p->state], p->processor_number,
														p->stats.time_run, p->pt.size, p->cmd);
	}
	//printf("Process State:\t%d\n", p->state);
	/*more to come*/
	//printf("-----\n");
}

//print page table for a specific process
void print_page_table(struct process* p)
{
  struct page_desc* page = p->pt.head;
  printf("Page Table ID: %d\n", p->pid);
  printf("\tPGID\tState\t\tOffset\n");
  printf("  ---------------------------------------------------------\n");
  while(page != NULL)
  {
    printf("\t%d\t%s\t\t%d\n", page->page_id, page_state_names[(int)page->state], page->offset);
    page = page->next;
  }
  printf("  ---------------------------------------------------------\n");
}

extern struct page_desc pages[N_PAGES];
extern struct page_desc *pages_main[MAIN_PAGES];
extern struct page_desc *pages_bs[BS_PAGES];
//print main memory information
void print_main_memory()
{
  int i = 0;
  int n_kernel_pages = 0;
  int n_user_pages = 0;
  int free_pages = 0;
  printf("\tPID\tPGID\tState\t\tOffset\n");
  printf("  ---------------------------------------------------------\n");
  for(i = 0; i < MAIN_PAGES; i++)
  {
    if(pages_main[i] == NULL)
    {
      free_pages++;
      continue;
    }
    else if(pages_main[i]->is_kernel_page)
    {
      n_kernel_pages++;
    }
    else
    {
      n_user_pages++;
    }
    
    printf("\t%d\t%d\t%s\t\t%d\n",pages_main[i]->owner->pid, pages_main[i]->page_id, page_state_names[(int)pages_main[i]->state], pages_main[i]->offset);
  }
  printf("  ---------------------------------------------------------\n");
  printf("MAIN MEMORY\n");
  printf("==========\nTotal Pages: \t%d\nKernel Pages: \t%d\t%2.2f%%\nUser Pages: \t%d\t%2.2f%%\nFree Pages: \t%d\t%2.2f%%\n==========\n", (int)MAIN_PAGES, n_kernel_pages, 100*(float)n_kernel_pages/(float)MAIN_PAGES, n_user_pages, 100*(float)n_user_pages/(float)MAIN_PAGES, free_pages, 100*(float)free_pages/(float)MAIN_PAGES);
}

void print_bs()
{
  int i = 0;
  int n_kernel_pages = 0;
  int n_user_pages = 0;
  int free_pages = 0;
  printf("\tPID\tPGID\tState\t\tOffset\n");
  printf("  ---------------------------------------------------------\n");
  for(i = 0; i < BS_PAGES; i++)
  {
    if(pages_bs[i] == NULL)
    {
      free_pages++;
      continue;
    }
    else if(pages_bs[i]->is_kernel_page)
    {
      n_kernel_pages++;
    }
    else
    {
      n_user_pages++;
    }
    
    printf("\t%d\t%d\t%s\t\t%d\n",pages_bs[i]->owner->pid, pages_bs[i]->page_id, page_state_names[(int)pages_bs[i]->state], pages_bs[i]->offset);
  }
  printf("  ---------------------------------------------------------\n");
  printf("BACKING STORE MEMORY\n");
  printf("==========\nTotal Pages: \t%d\nKernel Pages: \t%d\t%2.2f%%\nUser Pages: \t%d\t%2.2f%%\nFree Pages: \t%d\t%2.2f%%\n==========\n", (int)BS_PAGES, n_kernel_pages, 100*(float)n_kernel_pages/(int)BS_PAGES, n_user_pages, 100*(float)n_user_pages/(int)BS_PAGES, free_pages, 100*(float)free_pages/(int)BS_PAGES);
}

void print_all_memory()
{
  int i = 0;
  int n_kernel_pages = 0;
  int n_user_pages = 0;
  int free_pages = 0;
  for(i = 0; i < N_PAGES; i++)
  {
    if(pages[i].is_kernel_page)
    {
      n_kernel_pages++;
    }
    else
    {
      n_user_pages++;
    }
  }
  printf("ALL PAGES, MAIN & BACKING STORE\n");
  printf("==========\nTotal Pages: \t%d\nKernel Pages: \t%d\t%2.2f%%\nUser Pages: \t%d\t%2.2f%%\nFree Pages: \t%d\t%2.2f%%\n==========\n", (int)N_PAGES, n_kernel_pages, 100*(float)n_kernel_pages/(int)N_PAGES, n_user_pages, 100*(float)n_user_pages/(int)N_PAGES, free_pages, 100*(float)free_pages/(int)N_PAGES);
}

void print_system_pages()
{
  int i = 0, j=0;
  struct process** list = get_all_processes(&i);
  struct process* p;
  for(j = 0; j < i; j++)
  {
		p = list[j];
    if(p->pid == 0)
    {
      print_page_table(p);
    }
  }
}

void print_user_pages()
{
  int i = 0, j=0;
  struct process** list = get_all_processes(&i);
  struct process* p;
  for(j = 0; j < i; j++)
  {
    p = list[j];
    if(p->pid != 0)
    {
      print_page_table(p);
    }
  }
}

//prints only the id of the process
void print_pid(struct process* p)
{
	printf("\nPID:	%d\n", p->pid);
}

//prints a queue
void print_queue(struct queue_definition *q)
{
	struct process *p_iter = q->head;
	if(p_iter != NULL)
	{
		if(p_iter->next_p == NULL)
			printf("\n HEAD(%d)", p_iter->pid);
		else
			printf("\n HEAD(%d)-->", p_iter->pid);
		p_iter = p_iter->next_p;
	}
	else
	{
		printf(" EMPTY");
	}
	while(p_iter != NULL)
	{
		if(p_iter->next_p != NULL)
		{
			printf("(%d)-->", p_iter->pid);
		}
		else
		{
			printf("TAIL(%d)", p_iter->pid);
		}
		
		p_iter = p_iter->next_p;
	}
}

const char *action_names[] = {"FREE","STORE","RETRV"};
void print_page_action(struct page_action *pa){
	// action name - owner process id - page_num - mem_offset
	printf("%s\t%d\t%d\t%d\t%d",action_names[pa->op],pa->subject->owner->pid,
									pa->subject->page_id, pa->source_offset, pa->target_offset);

}
void print_bs_queue(){
	struct page_action *pa = bs_queue.head;
	printf("ACTN\tPID\tPGID\tSRC\tTRGT\n========================================\n");
	while(pa != NULL){
		print_page_action(pa);
		printf("\n");
		pa = pa->next;	
	}
}

void print_running()
{
	int iter = 0;
	printf("Proc\tPID\tGR\n");
	printf("====================");
	for(;iter < NUM_PROC; iter++)
	{
		if(running_list[iter] != NULL)
			printf("\n%d\t%d\t%d", iter,
									running_list[iter]->pid,running_list[iter]->sched.group_no);
		else
			printf("\n%d\tNONE", iter);
	}
}

void print_all_queues()
{
	printf("New:");
	print_queue(&new_queue);
	printf("\nReady:");
	print_queue(&ready_queue);
	printf("\nWaiting:");
	print_queue(&waiting_queue);
	printf("\nTerminated:");
	print_queue(&terminated_queue);
	printf("\nRunning:\n");
	print_running();
}

// For sorting
static int pid_compare(const void* p1, const void* p2){
	return (*(struct process**)p1)->pid - (*(struct process**)p2)->pid;
}

void do_ps(){

  int i = 0;
	struct process **list = get_all_processes(&i);
	int j;
	
	// i is the size of the list.
	//printf("before sorting. i=%d\n",i);
	qsort(list,i,sizeof(struct process*),pid_compare);
	//printf("after sorting\n");
	print_process_list_header(1);
	for(j=0; j < i; j++){
		print_process(list[j]);
	}
		
	printf(" Total %d process(es)\n",i);

/*
	for(j=0; j < MAX_PROCS; j++){
		printf("&procs[j] = %d\n",(int)(&procs[j]));
		print_process(&procs[j]);
	}
*/

	free(list);
}


struct process* find_process_from_input(){
	int pid = -1;
	struct process *p;
	char *pidstr = strtok(NULL," \n");
	if(pidstr == NULL || sscanf(pidstr,"%d",&pid) != 1){
		printf("Invalid or missing pid\n");
		return NULL;
	}
	p = get_process_by_pid(pid);
	if(p == NULL){
		printf("Process %d not found\n",pid);
		return NULL;
	}
	return p;
}

int main(int argc, char *argv[]){

	//program variables
	///////////////////
	
	//for getting commands
	char *user_input;
	char *user_input_arg;
	
	struct process *p;

	//a file pointer for input so getting input from a file is convenient
	FILE *input_file;
	
	//for ending ui loop
	int run = 1;
	int prompt_on = 1;

	//test for input file as command line argument
	if(argc == 2)
	{
		input_file = fopen(argv[1], "r");
		prompt_on = 0;
	}
	else
	{
		input_file = stdin;
	}

	// Boot up.
	boot_daha();
	
	
	//Program UI
	while(run)
	{
		//prompt user for input
		//printf("\n");
		int num_chars = 250;
		char str[num_chars];
		//printf("\033[0;32;40m> \000");
		printf("\x1b[01;32mdaha[%06d] > \x1b[0m",get_sched_state()->current_cycle);
		//if(prompt_on) printf("> ");
		if(fgets(str, num_chars, input_file) == NULL) break;
		if(!prompt_on) printf("%s",str);
		user_input = strtok(str, " \n");
		
		//printf("--%s--\n",user_input);
		
		//check against known commands
		///////////
		//any state transition requires a pid
		///////////
		//create a new process, goes in the new queue
		//unrecognized command
		if(user_input == NULL || strcmp(user_input,"") == 0 || user_input[0] == '#')
		{
			// do nothing
		}
		else if(strcasecmp(user_input, "ia") == 0)
		{
			// Switch to interactive mode
			if(prompt_on == 0) fclose(input_file);			
			prompt_on = 1;
			input_file = stdin;
		}		
		///Here are the new commands for the Scheduler 03-30-11//
		//"Go" Command
		else if(strcasecmp(user_input, "GO") == 0)
		{
			int how_many = 0;
			how_many = go();//implemented in fs_sched.c
			if(how_many == 0)
			{
				printf(" All processors were full or no process was ready\n");
			}
			else
			{
				printf(" %d process(es) was started\n",how_many);
			}
		}
		//"EOQUANTUM" command
		else if(strcasecmp(user_input, "eoq") == 0 ||
									strcasecmp(user_input, "EOQUANTUM") == 0)
		{
			int pid = end_of_quantum();//implemented in fs_sched.c
			if(pid == 0){
				// could not preempt anything.
				printf(" Could not preempt any process\n");
			} else {
				p = get_process_by_pid(pid);
				print_process_list_header(0);
				print_process(p);
			}
		}
		//"CREATE" command
		else if(strcasecmp(user_input, "CREATE") == 0)
		{
			char* pid_str = strtok(NULL," \n");
			int pid;
			if(pid_str == NULL || sscanf(pid_str,"%d",&pid) != 1 || pid < 0){
				printf("Invalid or missing pid\n");
				continue;
			}
			p = get_process_by_pid(pid);
			if(p){
				printf(" Process with id %d already exists\n",pid);
				continue;
			}
			user_input = strtok(NULL,"\n");
			p = new_process(1,user_input,pid,1);
			if( p == NULL){
				printf("Cannot create process. Possibly wrong or invalid "
																											"group number.\n");
				continue;
			}
			queue_to_ready(p);
			print_process_list_header(0);
			print_process(p);
		}
//////////End Scheduler Interface Commands///////////////
		else if( strcasecmp(user_input, "new") == 0 )
		{
			char* gr_no_str = strtok(NULL," \n");
			int gr_no;
			if(gr_no_str == NULL || sscanf(gr_no_str,"%d",&gr_no) != 1){
				printf("Invalid or missing group number\n");
				continue;
			}
			// If the user supplied a command, lets use it.
			user_input = strtok(NULL,"\n");
			p = new_process(gr_no,user_input,-1,1);
			if( p == NULL){
				printf("Cannot create process. Possibly wrong or invalid "
																											"group number.\n");
				continue;
			}
			queue_to_ready(p);
			print_process_list_header(0);
			print_process(p);
		}
		//state transitions 1, 3, 5
		else if(strcasecmp(user_input, "ready") == 0 ||
									strcasecmp(user_input, "UNWAIT") == 0)
		{
			p = find_process_from_input();
			if(p == NULL) continue;
			if(queue_to_ready(p) != 0){
				printf("Illegal state transition\n");
			}
		}
		//state transition 2
		else if(strcasecmp(user_input, "run") == 0)
		{
			p = find_process_from_input();
			if(p == NULL) continue;
			if(queue_to_running(p) != 0){
				printf("Illegal state transition\n");
			}
		}
		//state transition 4
		else if(strcasecmp(user_input, "wait") == 0)
		{
			p = find_process_from_input();
			if(p == NULL) continue;
			if(queue_to_waiting(p) != 0){
				printf("Illegal state transition\n");
			}
		}
		//state transitions 6 and 7
		else if(strcasecmp(user_input, "kill") == 0
									|| strcasecmp(user_input, "terminate") == 0
									|| strcasecmp(user_input, "EOLIFE") == 0)
		{
			p = find_process_from_input();
			if(p == NULL) continue;
			if(queue_to_terminated(p) != 0){
				printf("Illegal state transition\n");
			}
		}
		//remove a process from the terminate queue
		else if(strcasecmp(user_input, "free") == 0)
		{
			p = find_process_from_input();
			if(p == NULL) {
				continue;
			}
			if(terminate_process(p) != 0){
				printf("Illegal state transition\n");
			}
		}
		//remove a process from the terminate queue
		else if(strcasecmp(user_input, "chgrp") == 0)
		{
			p = find_process_from_input();

			char* gr_no_str = strtok(NULL," \n");
			int gr_no;
			if(gr_no_str == NULL || sscanf(gr_no_str,"%d",&gr_no) != 1){
				printf("Invalid or missing group number\n");
				continue;
			}
			change_group(p,gr_no);
		}
		else if(strcasecmp(user_input, "ps") == 0)
		{
			do_ps();			
		}
		else if(strcasecmp(user_input, "si") == 0)
		{
			print_sched_state();
		}
		//The rest are for printing certain queues
		//it might be worth while to just enum the queues
		//rather than have a million different print commands
		//according to the enum in pm.h
		else if(strcmp(user_input, "list") == 0)
		{
			// What to list?
			user_input = strtok(NULL," \n");
			if(user_input == NULL || strcasecmp(user_input,"ALL") == 0) {
				print_all_queues();
			} else if(strcasecmp(user_input, "SCHED") == 0){
				p = peak(&ready_queue);
				if(p){
					printf(" Next process to be run:\n");
					print_process_list_header(0);
					print_process(p);
				} else {
					printf(" Nothing in the ready queue");
				}
			}	else if(strcasecmp(user_input, "NEW") == 0){
				printf("New:\t");
				print_queue(&new_queue);			
			} else if(strcasecmp(user_input, "READY") == 0){
				printf("Ready:\t");
				print_queue(&ready_queue);
			} else if(strcasecmp(user_input, "WAITING") == 0){
				printf("Waiting:\t");
				print_queue(&waiting_queue);
			} else if(strcasecmp(user_input, "TERMINATED") == 0){
				printf("Terminated:\t");
				print_queue(&terminated_queue);
			} else if(strcasecmp(user_input, "RUNNING") == 0){
				printf("Running:\t");
				print_running();
			} else if(strcasecmp(user_input, "mem") == 0){
        print_main_memory();
			} else if(strcasecmp(user_input, "bs") == 0){
        print_bs();
			} else if(strcasecmp(user_input, "allmem") == 0){
        print_all_memory();
			} else if(strcasecmp(user_input, "user") == 0){
        print_user_pages();
			} else if(strcasecmp(user_input, "system") == 0){
        print_system_pages();
			} else if(strcasecmp(user_input, "lrulist") == 0){
			  int i = 1;
			  struct page_desc* desc = lru_list.head;
			  printf("\tLRU#\tTableID\tPage_ID\tSTATE\tOffset\n-------------------------------------------\n");
			  while(desc != NULL)
			  {
			    printf("\t(%d)\t%d\t%d\t%s\t%d\n", i, desc->owner->pid, desc->page_id, page_state_names[(int)desc->state], desc->offset);
			    desc = desc->lru_next;
			    i++;
			  }
			} else if(strcasecmp(user_input, "lru") == 0){
		    if(lru_list.head != NULL)
		    {
			    print_page_table(get_process_by_pid(lru_list.head->owner->pid));
			    printf("LRU is PAGE \"%d\" in this table", lru_list.head->page_id);
			  } 
  			else
  			  printf("There is no LRU page");
			} else if(strcasecmp(user_input, "mru") == 0){
		    if(lru_list.tail != NULL)
		    {
			    print_page_table(get_process_by_pid(lru_list.tail->owner->pid));
			    printf("MRU is PAGE \"%d\" in this table", lru_list.tail->page_id);
		    }
  			else
  			  printf("There is no MRU page");
			} else if(strcasecmp(user_input, "pagetable") == 0 || strcasecmp(user_input, "pt") == 0){
			  p = find_process_from_input();
			  if(p == NULL)
			  {
			    printf("No such page table\n");
			    continue;
		    }
			    
				print_page_table(p);
			}
			else if(strcasecmp(user_input, "bsq") == 0)
			{
				print_bs_queue();
			}
			else {
				printf(" I don't know how to list '%s'",user_input);
			}
			printf("\n");		
		}
		else if(strcasecmp(user_input, "init_mem") == 0)
		{
			shutdown_daha();
			boot_daha();
		}
		else if(strcasecmp(user_input, "alloc_pt") == 0)
		{
			// Create a new process and set up its page table
			int n_pages;
			user_input_arg = strtok(NULL," \n");
			if(user_input_arg == NULL || sscanf(user_input_arg,"%d",&n_pages) != 1 || n_pages <= 0){
				printf("Invalid or missing page_table_size\n");
				continue;
			}
			// All new processes go into the group 1
			p = new_process(1,"",-1,n_pages);
			queue_to_ready(p);
			print_process_list_header(0);
			print_process(p);
			if(p->pt.size != n_pages) {
				printf("Not all requested pages were allocated. Requested:%d, "
															"Allocated:%d\n",n_pages,p->pt.size);
			}
		}
		else if(strcasecmp(user_input, "dealloc_pt") == 0)
		{	
			p = find_process_from_input();
			if(p == NULL) continue;
			if(queue_to_terminated(p) != 0){
				printf("Illegal state transition\n");
			}
		}
		else if(strcasecmp(user_input, "use") == 0)
		{
		  int page_id;
		  int ret = 0;
		  p = find_process_from_input();
			if(p == NULL)
			{
		    printf("Table not found.");
		    printf("Usage: page_fault <page_table_id> <page_id>\n");
		    continue;
			}
			
			//get page id
			user_input_arg = strtok(NULL, " \n");
		  if(user_input_arg == NULL || sscanf(user_input_arg, "%d", &page_id) != 1)
		  {
		    printf("Usage: page_fault <page_table_id> <page_id>\n");
		    continue;
		  }
			
			//call the function to use the page
			ret = use_page(p, page_id);
			if(ret == 0)
			{
			  printf("Page %d used\n", page_id);
			} else if(ret == -2) {
				printf("Page %d not found\n", page_id);
			} else if(ret == -3) {
				printf("Page %d is not yet in memory (needs a page fault).\n", page_id);
			}
		}
		else if(strcasecmp(user_input, "page_fault") == 0 || strcasecmp(user_input, "pf") == 0 )
		{
		  int page_id, result;
		  //verify user input
		  if((p = find_process_from_input()) == NULL)
		  {
		    printf("Table not found.");
		    printf("Usage: page_fault <page_table_id> <page_id>\n");
		    continue;
		  }

		  user_input_arg = strtok(NULL, " \n");
		  if(user_input_arg == NULL || sscanf(user_input_arg, "%d", &page_id) != 1)
		  {
		    printf("Usage: page_fault <page_table_id> <page_id>\n");
		    continue;
		  }

      result = handle_page_fault(p, page_id);
      switch(result)
      {
        case 0:
          //print_page_table(p);
          break;
        case -1:
          printf("Page does not exist!\n");
          break;
        case -2:
          printf("Page already in memory, or already faulted!\n");
          break;
        case -3:
          printf("No page to replace!\n");
          break;
        case -4:
          printf("BS queue is full, too many operations! (do a bs_interrupt to free up some queue space)\n");
          break;
        case -5:
          printf("Both main memory and the BS is full. Out of memory.\n");
          break;
        case 1:
          printf("Memory was full, and some other pages was queued to be swapped out first.\n");
          break;
      }
      //printf("Handling page fault: %d\n", handle_page_fault(p, page_num));
		}
		else if(strcasecmp(user_input, "bs_interrupt") == 0 || strcasecmp(user_input, "bsi") == 0 )
		{
		  int result;
		  int tbl_id, pg_id, src_offset, tgt_offset;
		  
			if(!bs_queue.head) 			
			{
			  printf("BS queue is empty, nothing to do\n");
			  continue;
			}
			
		  tbl_id = bs_queue.head->subject->owner->pid;
		  pg_id = bs_queue.head->subject->page_id;
		  src_offset = bs_queue.head->source_offset;
		  tgt_offset = bs_queue.head->target_offset;
		  
			result = bs_interrupt();
			if(result == 1)
			{
		    //the offset for backing store pages aren't set until they're processed
		    //src_offset = get_page(get_process_by_pid(tbl_id), pg_id)->offset;
		    printf("Page %d of table %d was swapped from main memory offset %d to the backing store at offset %d\n", pg_id, tbl_id, src_offset, tgt_offset);
		  }
		  else if(result == 2)
		  {
		    printf("Page %d of table %d was brought from BS offset %d into memory offset %d\n", pg_id, tbl_id, src_offset, tgt_offset);
	    }
		}
		else if(strcasecmp(user_input, "bsi_all") == 0 )
		{
			int out;
			do{
				//printf("calling bsi %d\n",n++);
				out = bs_interrupt();
			} while(out >= 0);
		}
		else if(strcmp(user_input, "q") == 0 || strcmp(user_input, "quit") == 0)
		{
			//user requests quit
			//printf("bye...\n");
			run = 0;
		}
		//unrecognized command
		else
		{
			printf("Unrecognized Command: '%s'\n", user_input);
		}
	}
	
	// Unload the kernel
	fclose(input_file);
	shutdown_daha();
	return 0;
}
